/******************************************************************************
Filename:     dma.c
Target:       cc2430
Revised:      16/12-2005
Revision:     1.0

Description:
    This example shows how to set up a DMA transfer between two RAM locations.
    See also other examples for DMA setup (e.g. AES, ADC_SERIES, FLASH).

******************************************************************************/
#include "app_ex.h"
#include <string.h>

// Prototypes
void initDma(void);
void dma_main(void);


/******************************************************************************
* @fn  initDma
*
* @brief
*      Initializes components for the DMA transfer application example.
*
* Parameters:
*
* @param  void
*
* @return void
*
******************************************************************************/
void initDma(void)
{
   initLcd();

   SET_MAIN_CLOCK_SOURCE(CRYSTAL);

   INIT_BUTTON();
   INIT_GLED();
   INIT_YLED();
}


/******************************************************************************
* @fn  dma_main
*
* @brief
*      Sets up the DMA to transfer data between to RAM locations, trigged by
*      external interrupt generated by button S1. Checks validity of data
*      after transfer.
*
* Parameters:
*
* @param  void
*
* @return void
*
******************************************************************************/
#ifdef COMPLETE_APPLICATION
void dma_main(void){
#else
void main(void){
#endif
   DMA_DESC dmaChannel;
   char sourceString[56] = "This is a test string used to demonstrate DMA transfer."; //56 bytes
   char destString[56];
   INT8 i;
   INT8 errors = 0;


   initDma();



   //Clearing the destination
   memset(destString,0,sizeof(destString));

     // Setting up the DMA channel.
   SET_WORD(dmaChannel.SRCADDRH, dmaChannel.SRCADDRL,   &sourceString); // The start address of the data to be transmitted
   SET_WORD(dmaChannel.DESTADDRH, dmaChannel.DESTADDRL, &destString);   // The start address of the destination.
   SET_WORD(dmaChannel.LENH, dmaChannel.LENL, sizeof(sourceString));    // Setting the number of bytes to transfer.
   dmaChannel.VLEN      = VLEN_USE_LEN;  // Using the length field to determine how many bytes to transfer.
   dmaChannel.PRIORITY  = PRI_HIGH;      // High priority.
   dmaChannel.M8        = M8_USE_8_BITS; // Irrelevant since length is determined by the LENH and LENL.
   dmaChannel.IRQMASK   = FALSE;         // The DMA shall not issue an IRQ upon completion.
   dmaChannel.DESTINC   = DESTINC_1;     // The destination address is to be incremented by 1 after each transfer.
   dmaChannel.SRCINC    = SRCINC_1;      // The source address inremented by 1 byte after each transfer.
   dmaChannel.TRIG      = DMATRIG_NONE;  // The DMA channel will be started manually.
   dmaChannel.TMODE     = TMODE_BLOCK;   // The number of bytes specified by LENH and LENL is transferred.
   dmaChannel.WORDSIZE  = WORDSIZE_BYTE; // One byte is transferred each time.


   // Using DMA channel 0.
   // Setting where the DMA channel is to read the desciptor and arming the DMA channel.
   DMA_SET_ADDR_DESC0(&dmaChannel);
   DMA_ABORT_CHANNEL(0);
   DMA_ARM_CHANNEL(0);

   //Waiting for the user to start the transfer.
   lcdUpdate((char*)"Press S1",(char*)"to start DMA.");
   while(!buttonPushed());


   // Clearing all DMA complete flags and starting the transfer.
   DMAIRQ = 0x00;
   DMA_START_CHANNEL(0);

   // Waiting for the DMA to finish.
   while(!(DMAIRQ & DMA_CHANNEL_0));




   // Verifying that data is transferred correctly
   for(i=0;i<sizeof(sourceString);i++)
   {
     if(sourceString[i] != destString[i])
         errors++;
   }


   //Displaying the result
   if(errors == 0)
   {lcdUpdate((char*)"Dma transfer",(char*)"correct!");}
   else
   {lcdUpdate((char*)"Error in DMA",(char*)"Transfer");}



   haltApplicationWithLED();
   return;
}


/******************************************************************************
* @fn  dma_init
*
* @brief
*      Initializes the DMA transfer application example.
*
* Parameters:
*
* @param  APPLICATION *a
*         Main application
*
* @return void
*
******************************************************************************/
#ifdef COMPLETE_APPLICATION
void dma_init(APPLICATION *a)
{
   a->menuText = (char*)"DMA";
   a->description = (char*)"Data transfer";
   a->main_func = dma_main;
}
#endif
